package com.apikey.auth.repository;

import com.apikey.auth.entity.History;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

/**
 * API Key历史记录数据访问层
 * 提供历史记录的数据库操作方法
 *
 * @author API Key Framework
 * @version 1.0
 */
@Repository
public interface HistoryRepository extends JpaRepository<History, Long>, JpaSpecificationExecutor<History> {

    /**
     * 根据API Key值查找历史记录
     *
     * @param keyValue API Key值
     * @param pageable 分页参数
     * @return 历史记录分页结果
     */
    Page<History> findByKeyValueAndIsDeletedFalse(String keyValue, Pageable pageable);

    /**
     * 根据用户ID查找历史记录
     *
     * @param userId   用户ID
     * @param pageable 分页参数
     * @return 历史记录分页结果
     */
    Page<History> findByUserIdAndIsDeletedFalse(String userId, Pageable pageable);

    /**
     * 根据操作者ID查找历史记录
     *
     * @param operatorId 操作者ID
     * @param pageable   分页参数
     * @return 历史记录分页结果
     */
    Page<History> findByOperatorIdAndIsDeletedFalse(String operatorId, Pageable pageable);

    /**
     * 根据操作类型查找历史记录
     *
     * @param operationType 操作类型
     * @param pageable      分页参数
     * @return 历史记录分页结果
     */
    Page<History> findByOperationTypeAndIsDeletedFalse(String operationType, Pageable pageable);

    /**
     * 根据时间范围查找历史记录
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param pageable  分页参数
     * @return 历史记录分页结果
     */
    Page<History> findByUpdatedAtBetweenAndIsDeletedFalse(LocalDateTime startTime, LocalDateTime endTime, Pageable pageable);

    /**
     * 查找所有未删除的历史记录
     *
     * @param pageable 分页参数
     * @return 历史记录分页结果
     */
    Page<History> findByIsDeletedFalse(Pageable pageable);

    /**
     * 统计历史记录总数
     *
     * @return 历史记录总数
     */
    @Query("SELECT COUNT(h) FROM History h WHERE h.isDeleted = false")
    long countByIsDeletedFalse();

    /**
     * 根据操作类型统计历史记录数量
     *
     * @param operationType 操作类型
     * @return 历史记录数量
     */
    @Query("SELECT COUNT(h) FROM History h WHERE h.operationType = :operationType AND h.isDeleted = false")
    long countByOperationTypeAndIsDeletedFalse(@Param("operationType") String operationType);

    /**
     * 获取操作类型分布统计
     *
     * @return 操作类型分布Map，key为操作类型，value为数量
     */
    @Query("SELECT h.operationType, COUNT(h) FROM History h WHERE h.isDeleted = false GROUP BY h.operationType")
    List<Object[]> getOperationTypeDistribution();

    /**
     * 获取每日操作统计
     *
     * @param days 统计天数
     * @return 每日操作统计列表
     */
    @Query(value = "SELECT DATE(updated_at) as date, COUNT(*) as count FROM history " +
            "WHERE is_deleted = false AND updated_at >= :startDate " +
            "GROUP BY DATE(updated_at) ORDER BY DATE(updated_at)", nativeQuery = true)
    List<Object[]> getDailyOperationStats(@Param("startDate") LocalDateTime startDate);

    /**
     * 获取指定API Key的完整变更时间线
     *
     * @param keyValue API Key值
     * @return 变更时间线列表
     */
    @Query("SELECT h FROM History h WHERE h.keyValue = :keyValue AND h.isDeleted = false ORDER BY h.updatedAt DESC")
    List<History> findTimelineByKeyValue(@Param("keyValue") String keyValue);

    /**
     * 查找需要清理的旧历史记录
     *
     * @param cutoffTime 截止时间
     * @return 需要清理的历史记录列表
     */
    @Query("SELECT h FROM History h WHERE h.isDeleted = true AND h.updatedAt < :cutoffTime")
    List<History> findOldDeletedRecords(@Param("cutoffTime") LocalDateTime cutoffTime);

    /**
     * 根据API Key值和操作类型查找最新的历史记录
     *
     * @param keyValue      API Key值
     * @param operationType 操作类型
     * @return 最新的历史记录
     */
    @Query("SELECT h FROM History h WHERE h.keyValue = :keyValue AND h.operationType = :operationType " +
            "AND h.isDeleted = false ORDER BY h.updatedAt DESC")
    List<History> findLatestByKeyValueAndOperationType(@Param("keyValue") String keyValue,
                                                       @Param("operationType") String operationType);

    /**
     * 获取最近的历史记录
     *
     * @param limit 限制数量
     * @return 最近的历史记录列表
     */
    @Query("SELECT h FROM History h WHERE h.isDeleted = false ORDER BY h.updatedAt DESC")
    List<History> findRecentHistory(Pageable pageable);

    /**
     * 根据用户ID和时间范围统计操作次数
     *
     * @param userId    用户ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 操作次数
     */
    @Query("SELECT COUNT(h) FROM History h WHERE h.userId = :userId " +
            "AND h.updatedAt BETWEEN :startTime AND :endTime AND h.isDeleted = false")
    long countByUserIdAndTimeRange(@Param("userId") String userId,
                                   @Param("startTime") LocalDateTime startTime,
                                   @Param("endTime") LocalDateTime endTime);

    /**
     * 根据操作者ID和时间范围统计操作次数
     *
     * @param operatorId 操作者ID
     * @param startTime  开始时间
     * @param endTime    结束时间
     * @return 操作次数
     */
    @Query("SELECT COUNT(h) FROM History h WHERE h.operatorId = :operatorId " +
            "AND h.updatedAt BETWEEN :startTime AND :endTime AND h.isDeleted = false")
    long countByOperatorIdAndTimeRange(@Param("operatorId") String operatorId,
                                       @Param("startTime") LocalDateTime startTime,
                                       @Param("endTime") LocalDateTime endTime);

    /**
     * 获取热门操作者统计
     *
     * @param limit 限制数量
     * @return 操作者统计列表
     */
    @Query("SELECT h.operatorId, COUNT(h) as count FROM History h " +
            "WHERE h.isDeleted = false AND h.operatorId IS NOT NULL " +
            "GROUP BY h.operatorId ORDER BY COUNT(h) DESC")
    List<Object[]> getTopOperators(Pageable pageable);

    /**
     * 获取热门用户统计
     *
     * @param limit 限制数量
     * @return 用户统计列表
     */
    @Query("SELECT h.userId, COUNT(h) as count FROM History h " +
            "WHERE h.isDeleted = false AND h.userId IS NOT NULL " +
            "GROUP BY h.userId ORDER BY COUNT(h) DESC")
    List<Object[]> getTopUsers(Pageable pageable);
}